<template>
    <main class="container overflow-hidden mx-auto p-8">
        <!-- 视频播放 -->
        <div v-show="currentVideo" class="mb-4">
            <!-- 标题 -->
            <div>
                <el-button type="danger" :size="elSize" class="mr-1.5" @click="turnDeleteVideoPasswordDialogShow(true)">删除</el-button>
                <h1 class="mb-2 inline">{{ currentVideo?.name }}</h1>
                <p class="text-xs text-gray-500">{{moment(currentVideo?.recordAt).fromNow()}}-{{moment(currentVideo?.recordAt).format("LLL")}}</p>
            </div>
            <!-- 标签 -->
            <div class="flex flex-wrap gap-2 my-2">
                <el-popconfirm v-for="tag in currentVideo?.videoTags" title="确认删除吗?" >
                    <template #reference>
                        <el-tag
                            type="primary"
                            closable
                            @close="tagOnClose(currentVideo!.videoId, tag.id)"
                        >
                            {{ tag.content }}
                        </el-tag>
                    </template>
                </el-popconfirm>
                <transition appear mode="out-in" @enter="tagInputOnEnter">
                    <el-tag v-if="!tagInputShow"
                            class="w-16 cursor-pointer"
                            type="info"
                            @click="turnTagInputShow(true)">+添加</el-tag>
                    <input v-else type="text"
                           class="rounded w-16 h-6 text-sm px-1.5 outline outline-1 outline-blue-500 shadow-lg"
                           v-model.trim="tagName"
                           ref="RefTagInput"
                           @blur="tagInputOnBlur(currentVideo!.videoId, tagName)"
                           @keydown.enter="tagInputOnBlur(currentVideo!.videoId, tagName)"
                    />
                </transition>
            </div>
            <div class="grid grid-cols-1 xl:grid-cols-2 gap-4">
                <video id="video-player"
                       :src="currentVideo?.src"
                       controls
                       muted
                       playsinline
                       class="aspect-video"
                >
                </video>
                <div>
                    <!-- 时间点 -->
                    <div class="flex flex-wrap gap-2">
                        <el-tag
                            v-for="starDuration in currentVideo?.durationTags"
                            type="success"
                            closable
                            @click.prevent="adjustProcess(starDuration.second)"
                            class="cursor-pointer"
                            @close="starDurationOnClose(currentVideo!.videoId, starDuration.id)"
                        >
                            {{ starDuration.content }}
                        </el-tag>
                        <transition appear mode="out-in" @enter="starDurationInputOnEnter">
                            <el-tag v-if="!starDurationInputShow"
                                    class="w-16 cursor-pointer"
                                    type="info"
                                    @click="turnStarDurationInputShow(true)">+添加</el-tag>
                            <input v-else type="text"
                                   class="rounded w-16 h-6 text-sm px-1.5 outline outline-1 outline-blue-500 shadow-lg"
                                   v-model.trim="starDurationComment"
                                   ref="RefStarDurationInput"
                                   @blur="starDurationInputOnBlur(currentVideo!.videoId, Player!.currentTime, starDurationComment)"
                                   @keydown.enter="starDurationInputOnBlur(currentVideo!.videoId, Player!.currentTime, starDurationComment)"
                            />
                        </transition>
                    </div>
                </div>
            </div>
        </div>
        <!-- 搜索 -->
        <div>
            <el-form @submit.prevent="keywordsOnSubmit(keywords)" class="flex justify-center">
                <div class="flex flex-wrap gap-x-2.5 justify-center">
                    <el-form-item>
                        <el-input v-model.trim="keywords"
                                  :prefix-icon="Search"
                                  clearable
                                  placeholder="搜索资源"
                                  type="text"
                                  @clear="keywordsOnSubmit(keywords)"
                                  :style="{width: keywordsInputWidth}"
                        />
                    </el-form-item>
                    <el-form-item>
                        <el-button native-type="submit" type="primary">搜索</el-button>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="randomPlay">随机</el-button>
                    </el-form-item>
                </div>
            </el-form>
        </div>
        <!-- 分页按钮 -->
        <div class="flex justify-center">
            <el-pagination :size="elSize"
                           :layout="pager.layout"
                           hide-on-single-page
                           v-model:page-size="pager.size"
                           v-model:current-page="pager.page"
                           :total="pager.total"
                           background
                           @change="pagerOnChange"
            />
        </div>
        <!-- 视频列表 -->
        <ul class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-6 my-6">
            <li v-for="video in videos" :key="video.videoId"
                class="group rounded-lg shadow-lg overflow-hidden cursor-pointer pb-2 hover:bg-yellow-50 transition-colors relative"
                :class="{'bg-sky-200/50': currentVideo?.videoId === video.videoId}"
                @click="videoListOnSelect(video)"
                @mouseenter="videoState[video.videoId+'-hover'] = true"
                @mouseleave="videoState[video.videoId+'-hover'] = false"
            >
                <img class="block w-full object-contain object-center aspect-video mb-2 animate__animated animate__fadeIn animate__fast"
                     :src="video.previewImg"
                     alt="无法加载"
                >
                <video v-if="videoState[video.videoId+'-previewVideoLoaded'] || (video.previewVideo && videoState[video.videoId+'-hover'])" autoplay loop muted :src="video.previewVideo"
                       class="aspect-video w-full absolute top-0 invisible group-hover:visible"
                       @loadeddata="videoState[video.videoId+'-previewVideoLoaded'] = true"
                ></video>
                <div class="info px-2 flex flex-col gap-y-1">
                    <p class="text-xs text-gray-500">{{moment(video.recordAt).fromNow()}}-{{moment(video.recordAt).format("LLL")}}</p>
                    <h1 class="truncate text-sm">{{video.name}}</h1>
                    <div v-show="video.videoTags.length>0" class="flex flex-wrap gap-1">
                        <el-tag v-for="tag in video.videoTags" :key="tag.id" type="primary" class="cursor-pointer">
                            {{ tag.content }}
                        </el-tag>
                    </div>
                    <div v-show="video.durationTags.length>0" class="flex flex-wrap gap-1">
                        <el-tag v-for="starDuration in video.durationTags" :key="starDuration.id" type="success"
                                @click.prevent="videoListOnSelect(video, starDuration.second)"
                                class="cursor-pointer"
                        >
                            {{ starDuration.content }}
                        </el-tag>
                    </div>
                </div>
            </li>
        </ul>
        <!-- 分页按钮 -->
        <div class="flex justify-center">
            <el-pagination :size="elSize"
                           :layout="pager.layout"
                           hide-on-single-page
                           v-model:page-size="pager.size"
                           v-model:current-page="pager.page"
                           :total="pager.total"
                           background
                           @change="pagerOnChange"
            />
        </div>
        <!-- 视频删除密码输入框 -->
        <el-dialog title="请输入密码来确认删除该视频" v-model="deleteVideoPasswordDialogIsShow">
            <el-form :model="deleteVideoFromData" id="deleteVideoFrom"
                     @submit.prevent="deleteVideo" :rules="deleteVideoFromRules"
                     ref="RefDeleteVideoFrom" label-width="auto"
            >
                <el-form-item label="视频id" prop="videoId">
                    <el-input v-model="deleteVideoFromData.videoId" disabled />
                </el-form-item>
                <el-form-item label="密码" prop="password" class="mb-0">
                    <el-input type="password" v-model="deleteVideoFromData.password"
                              ref="RefDeleteVideoPassword"
                    />
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="turnDeleteVideoPasswordDialogShow(false)">取消</el-button>
                <el-button type="danger" native-type="submit" form="deleteVideoFrom">确认</el-button>
            </template>
        </el-dialog>
    </main>
</template>

<script setup lang="ts">
import '@/assets/base.css'
import * as videoApi from '@/api/video'
import {onMounted, ref, nextTick, reactive} from 'vue'
import {Search} from "@element-plus/icons-vue";
import Plyr from 'Plyr'
import 'plyr/dist/plyr.css';
import {isMobile} from "@/utils/isMobile";
import * as screen from "@/utils/screenSize";
import {ElMessageBox, type FormRules, type FormInstance, type InputInstance} from "element-plus";
import moment from "moment";
import 'moment/dist/locale/zh-cn.js'
moment.locale('zh-cn');
moment.updateLocale('zh-cn', {
    relativeTime: {
        future: '%s后',
        past: '%s前',
        s: '几秒',
        ss: '%d秒',
        m: '1分钟',
        mm: '%d分钟',
        h: '1小时',
        hh: '%d小时',
        d: '1天',
        dd: '%d天',
        w: '1周',
        ww: '%d周',
        M: '1个月',
        MM: '%d个月',
        y: '1年',
        yy: '%d年',
    }
})

const elSize = ref<'small'|''|'large'>('small')

onMounted(()=>{
    // 加载视频
    loadVideos('', pager.value.page, pager.value.size)

    // 修改视频播放器的样式
    const videoEle = document.getElementById('video-player') as HTMLVideoElement;
    if (!videoEle) {
        return
    }
    Player.value = new Plyr(videoEle, {
        invertTime: false,
        fullscreen: {
            enabled: true,
            fallback: true,
            iosNative: true,
        },
        muted: true,
        controls() {
            if (isMobile()) {
                return ['play-large', 'play', 'progress', 'current-time', 'mute', 'fullscreen']
            }
            return ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'airplay', 'fullscreen']
        },
        keyboard: {
            focused: true,
            global: true,
        },
    });

    // 监听窗口大小变化
    const onScreenSizeChange = () => {
        let screenWidth = getScreenWidth();
        if (screenWidth >= screen.ScreenWidth.XL) {
            elSize.value = ''
            keywordsInputWidth.value = '300px'
            pager.value.layout = 'prev, pager, next, jumper, total'
        } else {
            elSize.value = 'small'
            keywordsInputWidth.value = '170px'
            pager.value.layout = 'prev, pager, next'
        }
    }
    onScreenSizeChange()
    screen.Listeners.XL.addEventListener('change', () => {
        setTimeout(onScreenSizeChange, 100)
    })
})

// 视频列表
const loadVideos = (keywords: string, page: number, size: number) => {
    videoApi.getVideoList({
        keywords, page, size,
    }).then(res => {
        if (res.data.data.page != pager.value.page || res.data.data.size !== pager.value.size) {
            return
        }
        videos.value = res.data.data.data
        pager.value.total = res.data.data.total!

        const params = new URLSearchParams(window.location.search);
        params.set('page', String(page));
        params.set('size', String(res.data.data.size));
        window.history.pushState({}, '', `?${params.toString()}`);
    });
}
const videos = ref<videoApi.Video[]>([]);
const videoState = reactive<Record<string, boolean>>({})
const keywords = ref('')
const keywordsInputWidth = ref('170px')
const keywordsOnSubmit = (keywords: string) => {
    pager.value.page = 1
    loadVideos(keywords, pager.value.page, pager.value.size)
}
const randomPlay = () => videoApi.getVideoByRandom({keywords: keywords.value}).then(res => currentVideo.value = res.data.data)
// 初始化页码
const urlQuery = new URLSearchParams(window.location.search);
const pager = ref({
    page: Number(urlQuery.get('page')) ? Number(urlQuery.get('page')) : 1,
    size: Number(urlQuery.get('size'))? Number(urlQuery.get('size')) : 16,
    total: 0,
    layout: 'prev, pager, next',
})
const pagerOnChange = (page: number, size: number) => loadVideos(keywords.value, page, size)
const videoListOnSelect = (video: videoApi.Video, second?: number) => {
    if (currentVideo.value?.videoId === video.videoId) {
        if (second && second > 0) {
            adjustProcess(second)
        }
    }else {
        currentVideo.value = video
        if (second && second > 0) {
            Player.value?.once('canplay', () => {
                adjustProcess(second)
            })
        }
    }
    jumpTop()
}

// 当前播放的视频
const Player = ref<InstanceType<typeof Plyr>|null>(null)
const currentVideo = ref<videoApi.Video>();
const adjustProcess = (second: number) => {
    if (!Player.value) {
        return
    }
    Player.value.currentTime = second
}
// 添加标签
const RefTagInput = ref<HTMLInputElement|null>(null)
const tagName = ref('')
const tagInputShow = ref(false)
const turnTagInputShow = (show: boolean) => {
    tagInputShow.value = show
    tagName.value = ''
}
const tagInputOnEnter = () => {
    if (tagInputShow.value) {
        nextTick(() => {
            RefTagInput.value?.focus()
        })
    }
}
const tagInputOnBlur = (videoId: string, tagName: string) => {
    if (tagName === '') {
        turnTagInputShow(false)
        return
    }
    videoApi.addVideoTagForVideo({
        videoId: videoId, name: tagName,
    }).then(res => {
        turnTagInputShow(false)
        if (currentVideo.value?.videoId !== videoId) {
            return
        }
        currentVideo.value!.videoTags.push({
            id: res.data.data.id, content: tagName
        })
    })
}
const tagOnClose = (videoId: string, tagId: number) => {
    ElMessageBox.confirm('确认删除吗?', '警告', {
        confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning',
    }).then(
        () => videoApi.deleteVideoTag({
            id: tagId,
        }).then(() => {
            if (currentVideo.value?.videoId!== videoId) {
                return
            }
            currentVideo.value!.videoTags = currentVideo.value!.videoTags.filter(tag => tag.id !== tagId)
        })
    )
}
// 添加时间点收藏
const RefStarDurationInput = ref<HTMLInputElement|null>(null)
const starDurationComment = ref('')
const starDurationInputShow = ref(false)
const turnStarDurationInputShow = (show: boolean) => {
    starDurationInputShow.value = show
    starDurationComment.value = ''
}
const starDurationInputOnEnter = () => {
    if (starDurationInputShow.value) {
        nextTick(() => {
            RefStarDurationInput.value?.focus()
        })
    }
}
const starDurationInputOnBlur = (videoId: string, second: number, comment: string) => {
    if (comment === '') {
        turnStarDurationInputShow(false)
        return
    }
    videoApi.addDurationTagForVideo({
        videoId: videoId, starSecond: second, content: comment,
    }).then(res => {
        turnStarDurationInputShow(false)
        if (currentVideo.value?.videoId !== videoId) {
            return
        }
        currentVideo.value!.durationTags.push({
            id: res.data.data.id, second, content: comment
        })
        // 按照时间顺序进行排序
        currentVideo.value!.durationTags.sort((a, b) => a.second - b.second)
    })
}
const starDurationOnClose = (videoId: string, starDurationId: number) => {
    ElMessageBox.confirm('确认删除吗?', '警告', {
        confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning',
    }).then(
        () => videoApi.deleteDurationTag({
            id: starDurationId,
        }).then(() => {
            if (currentVideo.value?.videoId!== videoId) {
                return
            }
            currentVideo.value!.durationTags = currentVideo.value!.durationTags.filter(starDuration => starDuration.id !== starDurationId)
        })
    )
}

function jumpTop() {
    document.scrollingElement!.scrollTo({
        behavior: 'smooth',
        top: 0,
    })
}

function getScreenWidth() {
    return window.innerWidth
}

// 删除视频对话框是否显示
const deleteVideoPasswordDialogIsShow = ref(false)
// 开关删除视频对话框
const RefDeleteVideoPassword = ref<InputInstance|null>(null)
const turnDeleteVideoPasswordDialogShow = (show: boolean) => {
    deleteVideoPasswordDialogIsShow.value = show;
    if (show) {
        deleteVideoFromData.videoId = currentVideo.value?.videoId!
        nextTick(() => setTimeout(() => {
            RefDeleteVideoPassword.value?.focus()
        }, 100))
    }
}
// 删除视频表单
const RefDeleteVideoFrom = ref<FormInstance|null>(null)
// 删除视频请求表单
const deleteVideoFromData = reactive({
    videoId: '',
    password: '',
})
// 删除视频表单验证规则
const deleteVideoFromRules = reactive<FormRules>({
    videoId: {
        required: true,
        message: '请选择视频',
        trigger: 'change',
    },
    password: {
        required: true,
        message: '请输入密码',
        trigger: 'change',
    }
})
// 删除视频请求
const deleteVideo = async () => {
    await RefDeleteVideoFrom.value!.validate();
    const resp = await videoApi.deleteVideo(deleteVideoFromData);
    videos.value = videos.value.filter(video => video.videoId !== resp.data.data.videoId)
    turnDeleteVideoPasswordDialogShow(false)
    if (currentVideo.value?.videoId === resp.data.data.videoId) {
        currentVideo.value = undefined;
    }
}

</script>
